/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.audioeditor.soundmanagers;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.tritonus.share.sampled.file.TAudioFileFormat;

/**
 *
 * @author Ahmed
 */
public class FileSoundManager implements SoundManager {

    File f = null;
    private Map<Object, Object> audioProps;
    AudioInputStream ais = null;

    @Override
    public void handleSound(Object soundSource) {
        try {
            f = (File) soundSource;
            AudioFileFormat baseFileFormat = null;

            baseFileFormat = AudioSystem.getAudioFileFormat(f);
            ais = AudioSystem.getAudioInputStream(f);
            // TAudioFileFormat properties
            if (baseFileFormat instanceof TAudioFileFormat) {
                Map properties = baseFileFormat.properties();
                setAudioProps(properties);

            }
        } catch (UnsupportedAudioFileException | IOException ex) {
            Logger.getLogger(FileSoundManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String mergeFiles(int[] starts, int[] ends, File[] files, File out) {
        String data = "";
        FileOutputStream fis = null;
        try {
            fis = new FileOutputStream(out);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(FileSoundManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        for (int i=0;i<starts.length;i++) {
            System.out.println("file no."+i+":"+files[i]);
            System.out.println("start no."+i+":"+starts[i]);
            System.out.println("end no."+i+":"+ends[i]);
            data+="\nfile no."+i+":"+files[i];
            data+="\nstart time no."+i+":"+starts[i];
            data+="\nend time no."+i+":"+ends[i];
            handleSound(files[i]);
            try {

                int numBytesRead = 0;
                int numFramesRead = 0;
                long totalFramesRead = 0;



                int bytesPerFrame = (int) getAudioProps().get("mp3.framesize.bytes");
                float fps = (float) getAudioProps().get("mp3.framerate.fps");
                System.out.println("fps=" + fps);

                long startframe = (long) (starts[i] * fps);
                long endframe = (long) (ends[i] * fps);

                int totalFrame = (int) (endframe - startframe);

                int numBytes = 1024 * bytesPerFrame;
                System.out.println("Total frames=" + totalFrame);
                //System.out.println("fps="+fps);
                //System.out.println("total frames="+totalFrame);

                byte[] audioBytes = new byte[totalFrame];
                ais.skip(startframe);
                // Try to read numBytes bytes from the file.
                while ((numBytesRead =
                        ais.read(audioBytes)) != -1 && totalFramesRead <= totalFrame) {
                    // Calculate the number of frames actually read.
                    numFramesRead = numBytesRead / bytesPerFrame;
                    totalFramesRead += numFramesRead;
                    //      System.out.println("total frames red="+totalFramesRead);
                    // Here, do something useful with the audio data that's 
                    // now in the audioBytes array...
                    fis.write(audioBytes);
                }

            } catch (IOException ex) {
                Logger.getLogger(FileSoundManager.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return data;
    }

    public boolean saveAudio(File f, int start, int end) {

        boolean saved = false;
        try {
            FileOutputStream fis = new FileOutputStream(f);
            int numBytesRead = 0;
            int numFramesRead = 0;
            long totalFramesRead = 0;



            int bytesPerFrame = (int) getAudioProps().get("mp3.framesize.bytes");
            float fps = (float) getAudioProps().get("mp3.framerate.fps");
            System.out.println("fps=" + fps);

            long startframe = (long) (start * fps);
            long endframe = (long) (end * fps);

            int totalFrame = (int) (endframe - startframe);

            int numBytes = 1024 * bytesPerFrame;
            System.out.println("Total frames=" + totalFrame);
            //System.out.println("fps="+fps);
            //System.out.println("total frames="+totalFrame);

            byte[] audioBytes = new byte[totalFrame];
            ais.skip(startframe);
            // Try to read numBytes bytes from the file.
            while ((numBytesRead =
                    ais.read(audioBytes)) != -1 && totalFramesRead <= totalFrame) {
                // Calculate the number of frames actually read.
                numFramesRead = numBytesRead / bytesPerFrame;
                totalFramesRead += numFramesRead;
                //      System.out.println("total frames red="+totalFramesRead);
                // Here, do something useful with the audio data that's 
                // now in the audioBytes array...
                fis.write(audioBytes);
            }

        } catch (IOException ex) {
            Logger.getLogger(FileSoundManager.class.getName()).log(Level.SEVERE, null, ex);
        }

        return saved;
    }

    @Override
    public void operate() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    /**
     * @return the audioProps
     */
    public Map<Object, Object> getAudioProps() {
        return audioProps;
    }

    /**
     * @param audioProps the audioProps to set
     */
    public void setAudioProps(Map<Object, Object> audioProps) {
        this.audioProps = audioProps;
    }
}
